#include "Skinner_Brute.h"
#include "Log.h"

void Skinner_Brute::separate(Cluster *cluster) {
    LOG_ENTER(SKIN,"Skinner_Brute::separate");

    int n = cluster->span.n;
    LMO_Iterator first = cluster->span.start;

    // Step 2: double for-loop, looking for farthest neighbor.
    LMO_Iterator iter = first;

    LOG(SKIN) << "  starting double for-loop";

    bool *is_antipole = new bool[n];
    for (int i=0; i<n; i++) {
        is_antipole[i] = false;
    }
    cluster->antipoles.clear();

    for (int i=0; i<n; i++) {
        Labeled_Metric_Object *item = *iter++;
        int antipole_ID;

        LOG(SKIN) << "  item(i=" << i << ")=" << item;

        LMO_Iterator jter = first;
        int j_max;
        double max_dist = -1;
        for (int j=0; j<n; j++) {
            Labeled_Metric_Object *jtem = *jter++;

            LOG(SKIN) << "    jtem(j=" << j << ")=" << jtem;

            if (i == j) continue; // don't compare obj to itself
            double dist = item->distance(jtem);

            if (dist > max_dist) {
                max_dist = dist;
                antipole_ID = jtem->ID;
                j_max = j;
            }
        }

        LOG(SKIN) << "j_max=" << j_max;
        LOG(SKIN) << "saving antipole: src_ID=" << item->ID
                  << " dst_ID=" << antipole_ID
                  << " dist=" << max_dist;

        cluster->antipoles.insert(std::make_pair(item->ID, ID_Dist(antipole_ID, max_dist)));
        is_antipole[j_max] = true;
    }

    // Got all the antipoles.  Now separate the cluster into
    // interior and extreme subsets
    cluster->interior_set.clear();
    cluster->extreme_set.clear();
    iter = first;
    for (int i=0; i<n; i++) {
        if (is_antipole[i]) {
            cluster->extreme_set.append(*iter);
        }
        else {
            cluster->interior_set.append(*iter);
        }
        iter++;
    }

    delete[] is_antipole;

    LOG_EXIT();
}
